<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="robots" content="noodp" />
        <title>Go语言上手（一） | 青训营笔记 - L_B__</title><meta name="referrer" content="no-referrer">
<meta name="description" content="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。"><meta property="og:title" content="Go语言上手（一） | 青训营笔记" />
<meta property="og:description" content="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" /><meta property="og:image" content="https://acking-you.github.io/logo.png"/><meta property="article:section" content="posts" />
<meta property="article:published_time" content="2022-05-07T00:00:00+00:00" />
<meta property="article:modified_time" content="2022-05-07T00:00:00+00:00" />

<meta name="twitter:card" content="summary_large_image"/>
<meta name="twitter:image" content="https://acking-you.github.io/logo.png"/>

<meta name="twitter:title" content="Go语言上手（一） | 青训营笔记"/>
<meta name="twitter:description" content="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。"/>
<meta name="application-name" content="FeelIt">
<meta name="apple-mobile-web-app-title" content="FeelIt"><meta name="theme-color" content="#ffffff"><meta name="msapplication-TileColor" content="#da532c"><link rel="canonical" href="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" /><link rel="prev" href="https://acking-you.github.io/posts/%E5%AE%9E%E7%8E%B0%E5%AE%9E%E6%97%B6qq%E5%A5%BD%E5%8F%8B%E6%90%9C%E7%B4%A2%E6%A1%86/" /><link rel="next" href="https://acking-you.github.io/posts/golang-note2/" /><link rel="stylesheet" href="/css/page.min.css"><link rel="stylesheet" href="/css/home.min.css"><script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "BlogPosting",
        "headline": "Go语言上手（一） | 青训营笔记",
        "inLanguage": "zh-CN",
        "mainEntityOfPage": {
            "@type": "WebPage",
            "@id": "https:\/\/acking-you.github.io\/posts\/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0\/"
        },"genre": "posts","keywords": "Go语言上手","wordcount":  5156 ,
        "url": "https:\/\/acking-you.github.io\/posts\/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0\/","datePublished": "2022-05-07T00:00:00+00:00","dateModified": "2022-05-07T00:00:00+00:00","publisher": {
            "@type": "Organization",
            "name": "作者"},"author": {
                "@type": "Person",
                "name": "作者"
            },"description": "这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。"
    }
    </script></head><body data-header-desktop="auto" data-header-mobile="auto"><script>(window.localStorage && localStorage.getItem('theme') ? localStorage.getItem('theme') === 'dark' : ('auto' === 'auto' ? window.matchMedia('(prefers-color-scheme: dark)').matches : 'auto' === 'dark')) && document.body.setAttribute('theme', 'dark');</script>

        <div id="mask"></div><div class="wrapper"><header class="desktop" id="header-desktop">
    <div class="header-wrapper">
        <div class="header-title">
            <a href="/" title="L_B__">L_B__</a>
        </div>
        <div class="menu">
            <div class="menu-inner"><a class="menu-item" href="/posts/"> 文章 </a><a class="menu-item" href="/tags/"> 标签 </a><a class="menu-item" href="/categories/"> 分类 </a><span class="menu-item delimiter"></span><span class="menu-item search" id="search-desktop">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-desktop">
                        <a href="#" class="search-button search-toggle" id="search-toggle-desktop" title="搜索">
                            <i class="fas fa-search fa-fw"></i>
                        </a>
                        <a href="#" class="search-button search-clear" id="search-clear-desktop" title="清空">
                            <i class="fas fa-times-circle fa-fw"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-desktop">
                            <i class="fas fa-spinner fa-fw fa-spin"></i>
                        </span>
                    </span><a href="javascript:void(0);" class="menu-item theme-switch" title="切换主题">
                    <i class="fas fa-adjust fa-fw"></i>
                </a>
            </div>
        </div>
    </div>
</header><header class="mobile" id="header-mobile">
    <div class="header-container">
        <div class="header-wrapper">
            <div class="header-title">
                <a href="/" title="L_B__">L_B__</a>
            </div>
            <div class="menu-toggle" id="menu-toggle-mobile">
                <span></span><span></span><span></span>
            </div>
        </div>
        <div class="menu" id="menu-mobile"><div class="search-wrapper">
                    <div class="search mobile" id="search-mobile">
                        <input type="text" placeholder="搜索文章标题或内容..." id="search-input-mobile">
                        <a href="#" class="search-button search-toggle" id="search-toggle-mobile" title="搜索">
                            <i class="fas fa-search fa-fw"></i>
                        </a>
                        <a href="#" class="search-button search-clear" id="search-clear-mobile" title="清空">
                            <i class="fas fa-times-circle fa-fw"></i>
                        </a>
                        <span class="search-button search-loading" id="search-loading-mobile">
                            <i class="fas fa-spinner fa-fw fa-spin"></i>
                        </span>
                    </div>
                    <a href="#" class="search-cancel" id="search-cancel-mobile">
                        取消
                    </a>
                </div><a class="menu-item" href="/posts/" title="">文章</a><a class="menu-item" href="/tags/" title="">标签</a><a class="menu-item" href="/categories/" title="">分类</a><div class="menu-item"><a href="javascript:void(0);" class="theme-switch" title="切换主题">
                    <i class="fas fa-adjust fa-fw"></i>
                </a>
            </div></div>
    </div>
</header><div class="search-dropdown desktop">
    <div id="search-dropdown-desktop"></div>
</div>
<div class="search-dropdown mobile">
    <div id="search-dropdown-mobile"></div>
</div><main class="main">
                <div class="container"><div class="toc" id="toc-auto">
            <h2 class="toc-title">目录</h2>
            <div class="toc-content" id="toc-content-auto"></div>
        </div><article class="page single" data-toc="disable"><div class="featured-image"><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center"
        data-srcset="https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center, https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center 1.5x, https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center 2x"
        data-sizes="auto"
        alt="https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center"
        title="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。" /></div><div class="single-card" data-image="true"><h2 class="single-title animated flipInX">Go语言上手（一） | 青训营笔记</h2><div class="post-meta">
                <div class="post-meta-line"><span class="post-author"><a href="/" title="Author" rel=" author" class="author"><i class="fas fa-user-circle fa-fw"></i>作者</a></span>&nbsp;<span class="post-category">出版于  <a href="/categories/%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/"><i class="far fa-folder fa-fw"></i>青训营笔记</a></span></div>
                <div class="post-meta-line"><span><i class="far fa-calendar-alt fa-fw"></i>&nbsp;<time datetime="2022-05-07">2022-05-07</time></span>&nbsp;<span><i class="fas fa-pencil-alt fa-fw"></i>&nbsp;约 5156 字</span>&nbsp;
                    <span><i class="far fa-clock fa-fw"></i>&nbsp;预计阅读 11 分钟</span>&nbsp;</div>
            </div>
            
            <hr><div class="details toc" id="toc-static"  data-kept="">
                    <div class="details-summary toc-title">
                        <span>目录</span>
                        <span><i class="details-icon fas fa-angle-right"></i></span>
                    </div>
                    <div class="details-content toc-content" id="toc-content-static"><nav id="TableOfContents">
  <ul>
    <li><a href="#语法速览">语法速览</a>
      <ul>
        <li><a href="#基础语法">基础语法</a></li>
      </ul>
    </li>
    <li><a href="#实战项目">实战项目</a>
      <ul>
        <li><a href="#猜谜游戏pass过于简单">猜谜游戏（pass，过于简单）</a></li>
        <li><a href="#在线词典">在线词典</a></li>
        <li><a href="#socks5代理服务器">SOCKS5代理服务器</a></li>
      </ul>
    </li>
  </ul>
</nav></div>
                </div><div class="content" id="content"><p>这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。</p>
<h2 id="语法速览">语法速览</h2>
<h3 id="基础语法">基础语法</h3>
<p>基础语法有几点需要注意：</p>
<h4 id="第一类型">第一：类型</h4>
<blockquote>
<p>有值类型，有指针，指针只能作为引用的替代品，无法指针直接运算。</p>
</blockquote>
<p>go语言有值类型，可以直接像下面这样定义变量：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">Student</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">name</span> <span class="kt">string</span>
	<span class="nx">sid</span>  <span class="kt">string</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
	<span class="kd">var</span> <span class="nx">student</span> <span class="p">=</span> <span class="nx">Student</span><span class="p">{</span><span class="nx">name</span><span class="p">:</span> <span class="s">&#34;John&#34;</span><span class="p">,</span> <span class="nx">sid</span><span class="p">:</span> <span class="s">&#34;1001&#34;</span><span class="p">}</span>   <span class="c1">//student为值类型
</span><span class="c1"></span>    <span class="kd">var</span> <span class="nx">student</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">Student</span><span class="p">{</span><span class="nx">name</span><span class="p">:</span> <span class="s">&#34;John&#34;</span><span class="p">,</span> <span class="nx">sid</span><span class="p">:</span> <span class="s">&#34;1001&#34;</span><span class="p">}</span> <span class="c1">//student为指针类型（注意由于go有垃圾回收机制，所以这里会自动为我们开辟堆内存
</span><span class="c1"></span>    <span class="nx">student</span> <span class="o">:=</span> <span class="nb">new</span><span class="p">(</span><span class="nx">Student</span><span class="p">)</span> <span class="c1">//也可通过内置的new()函数直接开辟堆内存，而不立马初始化，得到一个指针
</span><span class="c1"></span><span class="p">}</span>

</code></pre></div><blockquote>
<p>go语言的切片</p>
</blockquote>
<p>同样切片类型也有上述两种获得内存的定义方式，也可通过内置的make函数对内部的cap和len进行初始的控制。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="nl">nums</span> <span class="p">:</span><span class="o">=</span> <span class="n">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span><span class="c1">//得到一个底层数组长度为2，cap为10的初始切片
</span><span class="c1"></span><span class="nl">nums1</span> <span class="p">:</span><span class="o">=</span> <span class="n">nums2</span><span class="p">[</span><span class="mi">0</span><span class="o">:</span><span class="mi">3</span><span class="p">]</span> <span class="c1">//第二种切片方式
</span></code></pre></div><h4 id="第二内置库部分">第二：内置库部分</h4>
<h5 id="json库的使用">json库的使用</h5>
<p>通过在字段后面跟着的字符串进行序列化的定义，后面跟着的称为域标签。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">package</span> <span class="n">main</span>

<span class="nf">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="n">type</span> <span class="n">Student</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">Name</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;name&#34;</span><span class="err">`</span>
	<span class="n">Sid</span>  <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;sid&#34;</span><span class="err">`</span>
<span class="p">}</span>

<span class="n">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nl">s</span> <span class="p">:</span><span class="o">=</span> <span class="n">Student</span><span class="p">{</span><span class="nl">Name</span><span class="p">:</span> <span class="s">&#34;jonh&#34;</span> <span class="p">,</span><span class="nl">Sid</span><span class="p">:</span> <span class="s">&#34;10323&#34;</span><span class="p">}</span>
	<span class="c1">//序列化
</span><span class="c1"></span>	<span class="n">p</span> <span class="p">,</span><span class="nl">err</span> <span class="p">:</span><span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">Marshal</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span><span class="o">!=</span><span class="n">nil</span> <span class="p">{</span>
		<span class="n">panic</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="n">fmt</span><span class="p">.</span><span class="n">Println</span><span class="p">(</span><span class="n">string</span><span class="p">(</span><span class="n">p</span><span class="p">))</span>
	
	<span class="c1">//反序列化
</span><span class="c1"></span>	<span class="n">err</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">Unmarshal</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="o">&amp;</span><span class="n">s</span><span class="p">)</span>
	<span class="k">if</span> <span class="n">err</span><span class="o">!=</span><span class="n">nil</span> <span class="p">{</span>
		<span class="n">panic</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="n">fmt</span><span class="p">.</span><span class="n">Println</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="p">}</span>

</code></pre></div><p>官方对域标签有以下说明：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="c1">// Field appears in JSON as key &#34;myName&#34;.
</span><span class="c1"></span><span class="n">Field</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;myName&#34;</span><span class="err">`</span>

<span class="c1">// Field appears in JSON as key &#34;myName&#34; and
</span><span class="c1">// the field is omitted from the object if its value is empty,
</span><span class="c1">// as defined above.
</span><span class="c1"></span><span class="n">Field</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;myName,omitempty&#34;</span><span class="err">`</span>

<span class="c1">// Field appears in JSON as key &#34;Field&#34; (the default), but
</span><span class="c1">// the field is skipped if empty.
</span><span class="c1">// Note the leading comma.
</span><span class="c1"></span><span class="n">Field</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;,omitempty&#34;</span><span class="err">`</span>

<span class="c1">// Field is ignored by this package.
</span><span class="c1"></span><span class="n">Field</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;-&#34;</span><span class="err">`</span>

<span class="c1">// Field appears in JSON as key &#34;-&#34;.
</span><span class="c1"></span><span class="n">Field</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;-,&#34;</span><span class="err">`</span>
</code></pre></div><h5 id="时间库的使用">时间库的使用</h5>
<p><strong>时间的获取</strong></p>
<blockquote>
<p>获取当前时间：</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">now</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span> <span class="c1">//获取当前时间
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;current time:%v\n&#34;</span><span class="p">,</span> <span class="nx">now</span><span class="p">)</span>
    <span class="nx">year</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Year</span><span class="p">()</span>     <span class="c1">//年
</span><span class="c1"></span>    <span class="nx">month</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Month</span><span class="p">()</span>   <span class="c1">//月
</span><span class="c1"></span>    <span class="nx">day</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Day</span><span class="p">()</span>       <span class="c1">//日
</span><span class="c1"></span>    <span class="nx">hour</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Hour</span><span class="p">()</span>     <span class="c1">//小时
</span><span class="c1"></span>    <span class="nx">minute</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Minute</span><span class="p">()</span> <span class="c1">//分钟
</span><span class="c1"></span>    <span class="nx">second</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Second</span><span class="p">()</span> <span class="c1">//秒
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d-%02d-%02d %02d:%02d:%02d\n&#34;</span><span class="p">,</span> <span class="nx">year</span><span class="p">,</span> <span class="nx">month</span><span class="p">,</span> <span class="nx">day</span><span class="p">,</span> <span class="nx">hour</span><span class="p">,</span> <span class="nx">minute</span><span class="p">,</span> <span class="nx">second</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><blockquote>
<p>获取时间戳</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">now</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>            <span class="c1">//获取当前时间
</span><span class="c1"></span>    <span class="nx">timestamp1</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Unix</span><span class="p">()</span>     <span class="c1">//时间戳
</span><span class="c1"></span>    <span class="nx">timestamp2</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">UnixNano</span><span class="p">()</span> <span class="c1">//纳秒时间戳
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;现在的时间戳：%v\n&#34;</span><span class="p">,</span> <span class="nx">timestamp1</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;现在的纳秒时间戳：%v\n&#34;</span><span class="p">,</span> <span class="nx">timestamp2</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><blockquote>
<p>时间戳与时间的转换</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">now</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>                  <span class="c1">//获取当前时间
</span><span class="c1"></span>    <span class="nx">timestamp</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Unix</span><span class="p">()</span>            <span class="c1">//时间戳
</span><span class="c1"></span>    <span class="nx">timeObj</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Unix</span><span class="p">(</span><span class="nx">timestamp</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1">//将时间戳转为时间格式
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">timeObj</span><span class="p">)</span>
    <span class="nx">year</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Year</span><span class="p">()</span>     <span class="c1">//年
</span><span class="c1"></span>    <span class="nx">month</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Month</span><span class="p">()</span>   <span class="c1">//月
</span><span class="c1"></span>    <span class="nx">day</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Day</span><span class="p">()</span>       <span class="c1">//日
</span><span class="c1"></span>    <span class="nx">hour</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Hour</span><span class="p">()</span>     <span class="c1">//小时
</span><span class="c1"></span>    <span class="nx">minute</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Minute</span><span class="p">()</span> <span class="c1">//分钟
</span><span class="c1"></span>    <span class="nx">second</span> <span class="o">:=</span> <span class="nx">timeObj</span><span class="p">.</span><span class="nf">Second</span><span class="p">()</span> <span class="c1">//秒
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d-%02d-%02d %02d:%02d:%02d\n&#34;</span><span class="p">,</span> <span class="nx">year</span><span class="p">,</span> <span class="nx">month</span><span class="p">,</span> <span class="nx">day</span><span class="p">,</span> <span class="nx">hour</span><span class="p">,</span> <span class="nx">minute</span><span class="p">,</span> <span class="nx">second</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><blockquote>
<p>获取星期几</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">t</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nf">Weekday</span><span class="p">().</span><span class="nf">String</span><span class="p">())</span>
<span class="p">}</span>
</code></pre></div><p><strong>时间的操作</strong></p>
<p>（1）Add(during)函数实现某个时间 + 时间间隔</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>
<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">now</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>
    <span class="nx">later</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Hour</span><span class="p">)</span> <span class="c1">// 当前时间加1小时后的时间
</span><span class="c1"></span>    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">later</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><p>（2）Sub(Time)获取时间差值</p>
<p>返回一个时间段 t - u 的值。如果结果超出了 Duration 可以表示的最大值或最小值，将返回最大值或最小值，要获取时间点 t - d（d 为 Duration），可以使用 t.Add(-d)。</p>
<p>（3）Equal(Time)判断时间是否相同</p>
<p>（4）Before 和 After某个时间是否在他之前或之后</p>
<p><strong>定时任务</strong></p>
<p>使用 time.Tick(时间间隔) 可以设置定时器，定时器的本质上是一个通道（channel）</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>
<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">ticker</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Tick</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span> <span class="c1">//定义一个1秒间隔的定时器
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">ticker</span> <span class="p">{</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="c1">//每秒都会执行的任务
</span><span class="c1"></span>    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div><p><strong>解析字符串格式的时间</strong></p>
<p>Parse 函数可以解析一个格式化的时间字符串并返回它代表的时间。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="nf">Parse</span><span class="p">(</span><span class="nx">layout</span><span class="p">,</span> <span class="nx">value</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="nx">Time</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span>
</code></pre></div><p>与 Parse 函数类似的还有 ParseInLocation 函数。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="nf">ParseInLocation</span><span class="p">(</span><span class="nx">layout</span><span class="p">,</span> <span class="nx">value</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">loc</span> <span class="o">*</span><span class="nx">Location</span><span class="p">)</span> <span class="p">(</span><span class="nx">Time</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span>
</code></pre></div><p>ParseInLocation 与 Parse 函数类似，但有两个重要的不同之处：</p>
<ul>
<li>第一，当缺少时区信息时，Parse 将时间解释为 UTC 时间，而 ParseInLocation 将返回值的 Location 设置为 loc；</li>
<li>第二，当时间字符串提供了时区偏移量信息时，Parse 会尝试去匹配本地时区，而 ParseInLocation 会去匹配 loc。</li>
</ul>
<p>示例代码如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>
<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;time&#34;</span>
<span class="p">)</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">layout</span> <span class="kt">string</span> <span class="p">=</span> <span class="s">&#34;2006-01-02 15:04:05&#34;</span>
    <span class="kd">var</span> <span class="nx">timeStr</span> <span class="kt">string</span> <span class="p">=</span> <span class="s">&#34;2019-12-12 15:22:12&#34;</span>
    <span class="nx">timeObj1</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Parse</span><span class="p">(</span><span class="nx">layout</span><span class="p">,</span> <span class="nx">timeStr</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">timeObj1</span><span class="p">)</span>
    <span class="nx">timeObj2</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">ParseInLocation</span><span class="p">(</span><span class="nx">layout</span><span class="p">,</span> <span class="nx">timeStr</span><span class="p">,</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Local</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">timeObj2</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><h5 id="字符串和数字互转">字符串和数字互转</h5>
<blockquote>
<p>字符串与数字互转的想关库函数全在一个包内：strconv包</p>
</blockquote>
<p>一图胜千言：</p>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd3af99c9e8d457c86005f95687aa058~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd3af99c9e8d457c86005f95687aa058~tplv-k3u1fbpfcp-watermark.image?, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd3af99c9e8d457c86005f95687aa058~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd3af99c9e8d457c86005f95687aa058~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd3af99c9e8d457c86005f95687aa058~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<h5 id="os相关信息">os相关信息</h5>
<blockquote>
<p>os包里面封装了很多和操作系统相关的内容。</p>
</blockquote>
<p>如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;os&#34;</span>
	<span class="s">&#34;os/exec&#34;</span>
<span class="p">)</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">)</span> <span class="c1">//打印命令行参数
</span><span class="c1"></span>	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nf">Getenv</span><span class="p">(</span><span class="s">&#34;PATH&#34;</span><span class="p">))</span> <span class="c1">//打印环境变量
</span><span class="c1"></span>	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">os</span><span class="p">.</span><span class="nf">Setenv</span><span class="p">(</span><span class="s">&#34;AA&#34;</span><span class="p">,</span><span class="s">&#34;BB&#34;</span><span class="p">))</span> <span class="c1">//设置环境变量，key,val形式设置
</span><span class="c1"></span>	<span class="nx">buf</span><span class="p">,</span><span class="nx">err</span> <span class="o">:=</span> <span class="nx">exec</span><span class="p">.</span><span class="nf">Command</span><span class="p">(</span><span class="s">&#34;grep&#34;</span><span class="p">).</span><span class="nf">CombinedOutput</span><span class="p">()</span> <span class="c1">//执行cmd命令
</span><span class="c1"></span>	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">buf</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div><p>其他pass跳过</p>
<h2 id="实战项目">实战项目</h2>
<h3 id="猜谜游戏pass过于简单">猜谜游戏（pass，过于简单）</h3>
<h3 id="在线词典">在线词典</h3>
<blockquote>
<p>想要实现在线词典，首先就得用到别人的翻译引擎</p>
</blockquote>
<h4 id="第一步抓包得得到数据进行分析">第一步：抓包得得到数据进行分析</h4>
<p>以彩云词典为例：</p>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3d1d0fca51c48e1b5d60988d30c1a93~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3d1d0fca51c48e1b5d60988d30c1a93~tplv-k3u1fbpfcp-watermark.image?, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3d1d0fca51c48e1b5d60988d30c1a93~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3d1d0fca51c48e1b5d60988d30c1a93~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b3d1d0fca51c48e1b5d60988d30c1a93~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<p>从网页调试工具里面查看随时收发的网络数据包，挨个查看它们的response，如果里面的json数据出现翻译结果，那么说明这个包就是返回的翻译结果！</p>
<p>那么我们只需要让go语言来做同样的两件事：</p>
<ol>
<li>发起请求。</li>
<li>解析返回的json内容。</li>
</ol>
<p>只要做好了这两件事，那么就很快得到了一个单词的翻译了。</p>
<h4 id="第二步利用工具生成代码">第二步：利用工具生成代码</h4>
<p>在此之前我们需要清楚有两个神器般存在的网站：</p>
<ol>
<li><a href="https://curlconverter.com/#go" target="_blank" rel="noopener noreffer">curlconverter</a> 把curl请求直接转为go的请求代码。</li>
<li><a href="https://oktools.net/json2go" target="_blank" rel="noopener noreffer">oktools</a> JSON转Golang Struct</li>
</ol>
<p>那么我们先肯定是要得到请求的代码，然后稍作更改，解析body后得出想要的结果。</p>
<h6 id="curl请求直接转为go的请求代码">curl请求直接转为go的请求代码</h6>
<blockquote>
<p>如下图进到刚才我们捕捉到的目标包，然后复制cURL，到网站进行解析得到最终代码。</p>
</blockquote>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b89931a7485e44bdb7f7a70418698933~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b89931a7485e44bdb7f7a70418698933~tplv-k3u1fbpfcp-watermark.image?, https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b89931a7485e44bdb7f7a70418698933~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b89931a7485e44bdb7f7a70418698933~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b89931a7485e44bdb7f7a70418698933~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;io/ioutil&#34;</span>
	<span class="s">&#34;log&#34;</span>
	<span class="s">&#34;net/http&#34;</span>
	<span class="s">&#34;strings&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">client</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">http</span><span class="p">.</span><span class="nx">Client</span><span class="p">{}</span>
	<span class="kd">var</span> <span class="nx">data</span> <span class="p">=</span> <span class="nx">strings</span><span class="p">.</span><span class="nf">NewReader</span><span class="p">(</span><span class="s">`{&#34;trans_type&#34;:&#34;en2zh&#34;,&#34;source&#34;:&#34;hello&#34;}`</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">http</span><span class="p">.</span><span class="nf">NewRequest</span><span class="p">(</span><span class="s">&#34;POST&#34;</span><span class="p">,</span> <span class="s">&#34;https://api.interpreter.caiyunai.com/v1/dict&#34;</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Connection&#34;</span><span class="p">,</span> <span class="s">&#34;keep-alive&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua&#34;</span><span class="p">,</span> <span class="s">`&#34; Not A;Brand&#34;;v=&#34;99&#34;, &#34;Chromium&#34;;v=&#34;99&#34;, &#34;Google Chrome&#34;;v=&#34;99&#34;`</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua-mobile&#34;</span><span class="p">,</span> <span class="s">&#34;?0&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;User-Agent&#34;</span><span class="p">,</span> <span class="s">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;app-name&#34;</span><span class="p">,</span> <span class="s">&#34;xy&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Content-Type&#34;</span><span class="p">,</span> <span class="s">&#34;application/json;charset=UTF-8&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Accept&#34;</span><span class="p">,</span> <span class="s">&#34;application/json, text/plain, */*&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;os-type&#34;</span><span class="p">,</span> <span class="s">&#34;web&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;X-Authorization&#34;</span><span class="p">,</span> <span class="s">&#34;token:qgemv4jr1y38jyq6vhvi&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua-platform&#34;</span><span class="p">,</span> <span class="s">`&#34;Windows&#34;`</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Origin&#34;</span><span class="p">,</span> <span class="s">&#34;https://fanyi.caiyunapp.com&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Site&#34;</span><span class="p">,</span> <span class="s">&#34;cross-site&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Mode&#34;</span><span class="p">,</span> <span class="s">&#34;cors&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Dest&#34;</span><span class="p">,</span> <span class="s">&#34;empty&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Referer&#34;</span><span class="p">,</span> <span class="s">&#34;https://fanyi.caiyunapp.com/&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Accept-Language&#34;</span><span class="p">,</span> <span class="s">&#34;zh-CN,zh;q=0.9&#34;</span><span class="p">)</span>
	<span class="nx">resp</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">client</span><span class="p">.</span><span class="nf">Do</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
	<span class="nx">bodyText</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ioutil</span><span class="p">.</span><span class="nf">ReadAll</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%s\n&#34;</span><span class="p">,</span> <span class="nx">bodyText</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><p>观察代码的改变我们只需对source部分的内容进行更改，即可得到对应的翻译结果。</p>
<h6 id="json转golang-struct">JSON转Golang Struct</h6>
<p>得到翻译结果，body内容后，我们需要把body内容解析为本地的sturct才能正常使用（当然你头铁的话可以直接找对应的字符串即可，也不需要反序列化。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="n">type</span> <span class="n">AutoGenerated</span> <span class="k">struct</span> <span class="p">{</span>
	<span class="n">Rc</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;rc&#34;</span><span class="err">`</span>
	<span class="n">Wiki</span> <span class="k">struct</span> <span class="p">{</span>
		<span class="n">KnownInLaguages</span> <span class="kt">int</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;known_in_laguages&#34;</span><span class="err">`</span>
		<span class="n">Description</span> <span class="k">struct</span> <span class="p">{</span>
			<span class="n">Source</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;source&#34;</span><span class="err">`</span>
			<span class="n">Target</span> <span class="n">interface</span><span class="p">{}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;target&#34;</span><span class="err">`</span>
		<span class="p">}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;description&#34;</span><span class="err">`</span>
		<span class="n">ID</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;id&#34;</span><span class="err">`</span>
		<span class="n">Item</span> <span class="k">struct</span> <span class="p">{</span>
			<span class="n">Source</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;source&#34;</span><span class="err">`</span>
			<span class="n">Target</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;target&#34;</span><span class="err">`</span>
		<span class="p">}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;item&#34;</span><span class="err">`</span>
		<span class="n">ImageURL</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;image_url&#34;</span><span class="err">`</span>
		<span class="n">IsSubject</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;is_subject&#34;</span><span class="err">`</span>
		<span class="n">Sitelink</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;sitelink&#34;</span><span class="err">`</span>
	<span class="p">}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;wiki&#34;</span><span class="err">`</span>
	<span class="n">Dictionary</span> <span class="k">struct</span> <span class="p">{</span>
		<span class="n">Prons</span> <span class="k">struct</span> <span class="p">{</span>
			<span class="n">EnUs</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;en-us&#34;</span><span class="err">`</span>
			<span class="n">En</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;en&#34;</span><span class="err">`</span>
		<span class="p">}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;prons&#34;</span><span class="err">`</span>
		<span class="n">Explanations</span> <span class="p">[]</span><span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;explanations&#34;</span><span class="err">`</span>
		<span class="n">Synonym</span> <span class="p">[]</span><span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;synonym&#34;</span><span class="err">`</span>
		<span class="n">Antonym</span> <span class="p">[]</span><span class="n">interface</span><span class="p">{}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;antonym&#34;</span><span class="err">`</span>
		<span class="n">WqxExample</span> <span class="p">[][]</span><span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;wqx_example&#34;</span><span class="err">`</span>
		<span class="n">Entry</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;entry&#34;</span><span class="err">`</span>
		<span class="n">Type</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;type&#34;</span><span class="err">`</span>
		<span class="n">Related</span> <span class="p">[]</span><span class="n">interface</span><span class="p">{}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;related&#34;</span><span class="err">`</span>
		<span class="n">Source</span> <span class="n">string</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;source&#34;</span><span class="err">`</span>
	<span class="p">}</span> <span class="err">`</span><span class="nl">json</span><span class="p">:</span><span class="s">&#34;dictionary&#34;</span><span class="err">`</span>
<span class="p">}</span>
</code></pre></div><h4 id="第三步更改代码实现功能">第三步：更改代码实现功能</h4>
<p>通过前面生成的代码已经能够实现请求和接收响应，且可以直接把响应内容反序列化为结构体，那么接下来，只需要把想要的部分遍历打印即可。</p>
<p>最终代码如下：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">src</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;bytes&#34;</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;io/ioutil&#34;</span>
	<span class="s">&#34;log&#34;</span>
	<span class="s">&#34;net/http&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">QueryCaiyun</span><span class="p">(</span><span class="nx">word</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">client</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">http</span><span class="p">.</span><span class="nx">Client</span><span class="p">{}</span>
	<span class="nx">request</span> <span class="o">:=</span> <span class="nx">DictRequestCaiyun</span><span class="p">{</span><span class="nx">TransType</span><span class="p">:</span> <span class="s">&#34;en2zh&#34;</span><span class="p">,</span> <span class="nx">Source</span><span class="p">:</span> <span class="nx">word</span><span class="p">}</span>
	<span class="nx">buf</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">(</span><span class="nx">request</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="kd">var</span> <span class="nx">data</span> <span class="p">=</span> <span class="nx">bytes</span><span class="p">.</span><span class="nf">NewReader</span><span class="p">(</span><span class="nx">buf</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">http</span><span class="p">.</span><span class="nf">NewRequest</span><span class="p">(</span><span class="s">&#34;POST&#34;</span><span class="p">,</span> <span class="s">&#34;https://api.interpreter.caiyunai.com/v1/dict&#34;</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Connection&#34;</span><span class="p">,</span> <span class="s">&#34;keep-alive&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua&#34;</span><span class="p">,</span> <span class="s">`&#34; Not A;Brand&#34;;v=&#34;99&#34;, &#34;Chromium&#34;;v=&#34;99&#34;, &#34;Google Chrome&#34;;v=&#34;99&#34;`</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua-mobile&#34;</span><span class="p">,</span> <span class="s">&#34;?0&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;User-Agent&#34;</span><span class="p">,</span> <span class="s">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;app-name&#34;</span><span class="p">,</span> <span class="s">&#34;xy&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Content-Type&#34;</span><span class="p">,</span> <span class="s">&#34;application/json;charset=UTF-8&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Accept&#34;</span><span class="p">,</span> <span class="s">&#34;application/json, text/plain, */*&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;os-type&#34;</span><span class="p">,</span> <span class="s">&#34;web&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;X-Authorization&#34;</span><span class="p">,</span> <span class="s">&#34;token:qgemv4jr1y38jyq6vhvi&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;sec-ch-ua-platform&#34;</span><span class="p">,</span> <span class="s">`&#34;Windows&#34;`</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Origin&#34;</span><span class="p">,</span> <span class="s">&#34;https://fanyi.caiyunapp.com&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Site&#34;</span><span class="p">,</span> <span class="s">&#34;cross-site&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Mode&#34;</span><span class="p">,</span> <span class="s">&#34;cors&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Sec-Fetch-Dest&#34;</span><span class="p">,</span> <span class="s">&#34;empty&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Referer&#34;</span><span class="p">,</span> <span class="s">&#34;https://fanyi.caiyunapp.com/&#34;</span><span class="p">)</span>
	<span class="nx">req</span><span class="p">.</span><span class="nx">Header</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;Accept-Language&#34;</span><span class="p">,</span> <span class="s">&#34;zh-CN,zh;q=0.9&#34;</span><span class="p">)</span>
	<span class="nx">resp</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">client</span><span class="p">.</span><span class="nf">Do</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">defer</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
	<span class="nx">bodyText</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ioutil</span><span class="p">.</span><span class="nf">ReadAll</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">if</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">StatusCode</span> <span class="o">!=</span> <span class="mi">200</span> <span class="p">{</span> <span class="c1">//防止返回错误
</span><span class="c1"></span>		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">&#34;bad Status code:&#34;</span><span class="p">,</span> <span class="nx">resp</span><span class="p">.</span><span class="nx">StatusCode</span><span class="p">,</span> <span class="s">&#34;body&#34;</span><span class="p">,</span> <span class="nb">string</span><span class="p">(</span><span class="nx">bodyText</span><span class="p">))</span>
	<span class="p">}</span>
	<span class="kd">var</span> <span class="nx">dictResponse</span> <span class="nx">DictResponseCaiyun</span>
	<span class="nx">err</span> <span class="p">=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">bodyText</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">dictResponse</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;translate from Caiyun\n&#34;</span><span class="p">,</span> <span class="s">&#34;UK:&#34;</span><span class="p">,</span> <span class="nx">dictResponse</span><span class="p">.</span><span class="nx">Dictionary</span><span class="p">.</span><span class="nx">Prons</span><span class="p">.</span><span class="nx">En</span><span class="p">,</span> <span class="s">&#34;US:&#34;</span><span class="p">,</span> <span class="nx">dictResponse</span><span class="p">.</span><span class="nx">Dictionary</span><span class="p">.</span><span class="nx">Prons</span><span class="p">.</span><span class="nx">EnUs</span><span class="p">)</span>
	<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">item</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">dictResponse</span><span class="p">.</span><span class="nx">Dictionary</span><span class="p">.</span><span class="nx">Explanations</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><h4 id="homework">homework</h4>
<p>后面我依次通过这个方式还弄了其他的翻译引擎，但是有很多翻译引擎的请求头都是动态实时的，或者加了密。我做的第二个有道的翻译引擎使用就是动态实时的，然后去查阅了破解方法，发现是通过阅读原本的js源码进行反推，得出请求头里面动态变化的内容。</p>
<p>最终写了Deepl和有道两个搜索引擎。</p>
<p>源码实现链接：<a href="https://github.com/ACking-you/TraningCamp/tree/master/lesson1/homework/simple_dict/src" target="_blank" rel="noopener noreffer">https://github.com/ACking-you/TraningCamp/tree/master/lesson1/homework/simple_dict/src</a></p>
<h3 id="socks5代理服务器">SOCKS5代理服务器</h3>
<h4 id="socks5简单介绍">SOCKS5简单介绍</h4>
<p>SOCKS5是代理协议，在使用TCP/IP协议通信的前端机器和服务器之间发挥中介作用，使内部网络的前端机器能够访问互联网的服务器，使通信更加安全。SOCKS5服务器将前端发送的请求转发给真正的目标服务器，模拟前端行为。此处，前端与SOCKS5之间也是通过TCP/IP协议进行通信的，前端向SOCKS5服务器发送请求发送给SOCKS5服务器，然后SOCKS5服务器将请求发送给真正的服务器。SOCKS5服务器在将通讯请求发送给真正服务器的过程中，对于请求数据包本身不加任何改变（明文传输）。SOCKS5服务器在收到真实服务器响应后，也原样转发到前端。</p>
<p>它的用途是， 比如某些企业的内网为了确保安全性，有很严格的防火墙策略，但是带来的副作用就是访问某些资源会很麻烦。 socks5 相当于在防火墙开了个口子，让授权的用户可以通过单个端口去访问内部的所有资源。实际上很多翻墙软件，最终暴露的也是一个 socks5 协议的端口。</p>
<h4 id="socks5代理原理">SOCKS5代理原理</h4>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8524dafa35a4a9399fc17c034846140~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8524dafa35a4a9399fc17c034846140~tplv-k3u1fbpfcp-watermark.image?, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8524dafa35a4a9399fc17c034846140~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8524dafa35a4a9399fc17c034846140~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e8524dafa35a4a9399fc17c034846140~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<p>正常浏览器访问一个网站，如果不经过代理服务器的话，就是先和对方的网站建立 TCP 连接，然后三次握手，握手完之后发起 HTTP 请求，然后服务返回 HTTP 响应。如果设置代理服务器之后，流程会变得复杂一些。 首先是浏览器和 socks5 代理建立 TCP 连接，代理再和真正的服务器建立 TCP 连接。这里可以分成四个阶段，<strong>握手阶段、认证阶段、请求阶段、 relay 阶段</strong>。</p>
<ul>
<li>握手阶段：浏览器会向 socks5 代理发送请求，包的内容包括一个协议的版本号，还有支持的认证的种类，socks5 服务器会选中一个认证方式，返回给浏览器。如果<strong>返回的是 00 的话就代表不需要认证</strong>，返回其他类型的话会开始认证流程，这里我们就不对认证流程进行概述了。（本次课程跳过认证阶段）</li>
<li>请求阶段：认证通过之后浏览器会对 socks5 服务器发起请求。主要信息包括 版本号，请求的类型，一般主要是 connection 请求，就代表代<strong>理服务器要和某个域名或者某个 IP 地址某个端口建立 TCP 连接</strong>。代理服务器收到响应之后，会真正和后端服务器建立连接，然后返回一个响应。</li>
<li>relay 阶段：此时浏览器会发送 正常发送请求，然后代理服务器接收到请求之后，会直接把请求转换到真正的服务器上。然后如果真正的服务器以后返回响应的话，那么也会把请求转发到浏览器这边。然后实际上 <strong>代理服务器并不关心流量的细节</strong>，可以是 HTTP流量，也可以是其它 TCP 流量。  这个就是 socks5 协议的工作原理。</li>
</ul>
<pre><code class="language-mermaid" data-lang="mermaid">graph LR
a[握手阶段]
b[认证阶段]
c[请求阶段]
d[转发relay阶段]
a--&gt;b--&gt;c--&gt;d

</code></pre><h4 id="具体实现">具体实现</h4>
<h5 id="v1-简单echo服务器">v1-简单echo服务器</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;bufio&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;log&#34;</span>
	<span class="s">&#34;net&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">server</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="s">&#34;tcp&#34;</span><span class="p">,</span> <span class="s">&#34;0.0.0.0:1080&#34;</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">for</span> <span class="p">{</span>
		<span class="nx">client</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">server</span><span class="p">.</span><span class="nf">Accept</span><span class="p">()</span>
		<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
			<span class="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Accept failed %v&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
			<span class="k">continue</span>
		<span class="p">}</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;连接成功! clent:%v \n&#34;</span><span class="p">,</span> <span class="nx">client</span><span class="p">.</span><span class="nf">RemoteAddr</span><span class="p">())</span>
		<span class="k">go</span> <span class="nf">process</span><span class="p">(</span><span class="nx">client</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">process</span><span class="p">(</span><span class="nx">conn</span> <span class="nx">net</span><span class="p">.</span><span class="nx">Conn</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">defer</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="nx">conn</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;连接断开! clent:%v \n&#34;</span><span class="p">,</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">RemoteAddr</span><span class="p">())</span>
	<span class="p">}()</span>

    <span class="c1">//用缓冲流进行一次包装，减少底层IO次数，让读取效率更高效
</span><span class="c1"></span>	<span class="nx">reader</span> <span class="o">:=</span> <span class="nx">bufio</span><span class="p">.</span><span class="nf">NewReader</span><span class="p">(</span><span class="nx">conn</span><span class="p">)</span>
	<span class="k">for</span> <span class="p">{</span>
		<span class="nx">b</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">reader</span><span class="p">.</span><span class="nf">ReadByte</span><span class="p">()</span>
		<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
			<span class="k">break</span>
		<span class="p">}</span>
		<span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">Write</span><span class="p">([]</span><span class="kt">byte</span><span class="p">{</span><span class="nx">b</span><span class="p">})</span>
		<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
			<span class="k">break</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><p><strong>客户端验证：</strong></p>
<p>没必要再写一个客户端，这时完全可以netcat工具进行tcp连接测试。</p>
<p>如下：</p>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7aaf956b1ab8433fa07d9c8b37ae3f7c~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7aaf956b1ab8433fa07d9c8b37ae3f7c~tplv-k3u1fbpfcp-watermark.image?, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7aaf956b1ab8433fa07d9c8b37ae3f7c~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7aaf956b1ab8433fa07d9c8b37ae3f7c~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7aaf956b1ab8433fa07d9c8b37ae3f7c~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<h5 id="v2-实现socks5的握手阶段">v2-实现SOCKS5的握手阶段</h5>
<p>实现SOCKS5之前我们需要清楚SOCKS5的握手阶段的请求和返回是怎么样的，如下面的图表所示：</p>
<table>
<thead>
<tr>
<th>VER</th>
<th>NMETHODS</th>
<th>METHODS</th>
</tr>
</thead>
<tbody>
<tr>
<td>1byte</td>
<td>1byte</td>
<td>1 to 255 byte</td>
</tr>
<tr>
<td>协议版本信息<em>socks5为0x05</em></td>
<td>支持认证的方法数量<em>值为0x00则表示无需认证</em></td>
<td>NMETHODS的值为多少METHODS就有多少个字节</td>
</tr>
</tbody>
</table>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kn">package</span> <span class="nx">main</span>

<span class="c1">//auth 阶段
</span><span class="c1"></span><span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;bufio&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;io&#34;</span>
	<span class="s">&#34;log&#34;</span>
	<span class="s">&#34;net&#34;</span>
<span class="p">)</span>
<span class="kd">const</span><span class="p">(</span>
	<span class="nx">socks5Ver</span> <span class="p">=</span> <span class="mh">0x05</span>
	<span class="nx">cmdBind</span> <span class="p">=</span> <span class="mh">0x01</span>
	<span class="nx">atypIPV4</span> <span class="p">=</span> <span class="mh">0x01</span>
	<span class="nx">atypeHOST</span> <span class="p">=</span> <span class="mh">0x03</span>
	<span class="nx">atypeIPV6</span> <span class="p">=</span> <span class="mh">0x04</span>
<span class="p">)</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">server</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="s">&#34;tcp&#34;</span><span class="p">,</span> <span class="s">&#34;0.0.0.0:1080&#34;</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">for</span> <span class="p">{</span>
		<span class="nx">client</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">server</span><span class="p">.</span><span class="nf">Accept</span><span class="p">()</span>
		<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
			<span class="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Accept failed %v&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
			<span class="k">continue</span>
		<span class="p">}</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;连接成功! clent:%v \n&#34;</span><span class="p">,</span> <span class="nx">client</span><span class="p">.</span><span class="nf">RemoteAddr</span><span class="p">())</span>
		<span class="k">go</span> <span class="nf">process</span><span class="p">(</span><span class="nx">client</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">process</span><span class="p">(</span><span class="nx">conn</span> <span class="nx">net</span><span class="p">.</span><span class="nx">Conn</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">defer</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="nx">conn</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;连接断开! clent:%v \n&#34;</span><span class="p">,</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">RemoteAddr</span><span class="p">())</span>
	<span class="p">}()</span>

	<span class="nx">reader</span> <span class="o">:=</span> <span class="nx">bufio</span><span class="p">.</span><span class="nf">NewReader</span><span class="p">(</span><span class="nx">conn</span><span class="p">)</span>
	<span class="nx">err</span> <span class="o">:=</span> <span class="nf">auth</span><span class="p">(</span><span class="nx">reader</span><span class="p">,</span><span class="nx">conn</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span><span class="o">!=</span><span class="kc">nil</span><span class="p">{</span>
		<span class="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;client %v auth failed:%v&#34;</span><span class="p">,</span><span class="nx">conn</span><span class="p">.</span><span class="nf">RemoteAddr</span><span class="p">(),</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;auth success&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">auth</span><span class="p">(</span><span class="nx">reader</span> <span class="o">*</span><span class="nx">bufio</span><span class="p">.</span><span class="nx">Reader</span><span class="p">,</span> <span class="nx">conn</span> <span class="nx">net</span><span class="p">.</span><span class="nx">Conn</span><span class="p">)</span> <span class="p">(</span><span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="c1">//协议版本
</span><span class="c1"></span>	<span class="nx">ver</span><span class="p">,</span><span class="nx">err</span> <span class="o">:=</span> <span class="nx">reader</span><span class="p">.</span><span class="nf">ReadByte</span><span class="p">()</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span><span class="p">{</span>
		<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;read ver failed:%w&#34;</span><span class="p">,</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">if</span> <span class="nx">ver</span> <span class="o">!=</span> <span class="nx">socks5Ver</span><span class="p">{</span>
		<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;not supported ver:%v&#34;</span><span class="p">,</span><span class="nx">ver</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c1">//支持的方法数量
</span><span class="c1"></span>	<span class="nx">methodSize</span><span class="p">,</span><span class="nx">err</span> <span class="o">:=</span> <span class="nx">reader</span><span class="p">.</span><span class="nf">ReadByte</span><span class="p">()</span>
	<span class="k">if</span> <span class="nx">err</span><span class="o">!=</span><span class="kc">nil</span><span class="p">{</span>
		<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;read methodSize failed:%w&#34;</span><span class="p">,</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="c1">//方法值
</span><span class="c1"></span>	<span class="nx">method</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">byte</span><span class="p">,</span><span class="nx">methodSize</span><span class="p">)</span>
	<span class="nx">_</span><span class="p">,</span><span class="nx">err</span> <span class="p">=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">ReadFull</span><span class="p">(</span><span class="nx">reader</span><span class="p">,</span><span class="nx">method</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span><span class="o">!=</span><span class="kc">nil</span><span class="p">{</span>
		<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;read method failed %w&#34;</span><span class="p">,</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">log</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;ver&#34;</span><span class="p">,</span><span class="nx">ver</span><span class="p">,</span><span class="s">&#34;method&#34;</span><span class="p">,</span><span class="nx">method</span><span class="p">)</span>

	<span class="c1">//返回的内容表示SOCKS5通信，且无需认证
</span><span class="c1"></span>	<span class="nx">_</span><span class="p">,</span><span class="nx">err</span> <span class="p">=</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">Write</span><span class="p">([]</span><span class="kt">byte</span><span class="p">{</span><span class="nx">socks5Ver</span><span class="p">,</span><span class="mh">0x00</span><span class="p">})</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span><span class="kc">nil</span><span class="p">{</span>
		<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;write failed:%w&#34;</span><span class="p">,</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="kc">nil</span>
<span class="p">}</span>

</code></pre></div><h5 id="v3-实现socks5的请求阶段">v3-实现SOCKS5的请求阶段</h5>
<p>同样来看看此时的消息协议：</p>
<p>客户端请求：</p>
<table>
<thead>
<tr>
<th>VER</th>
<th>CMD</th>
<th>RSV</th>
<th>ATYP</th>
<th>DST.ADDR</th>
<th>DST.PORT</th>
</tr>
</thead>
<tbody>
<tr>
<td>1byte</td>
<td>1byte</td>
<td>1byte</td>
<td>1byte</td>
<td>Variable</td>
<td>2byte</td>
</tr>
<tr>
<td>协议版本0x05为SOCKS5</td>
<td>代表请求类型<em>0x01表示CONNECT请求</em></td>
<td>保留字段（不理会）</td>
<td>目标地址类型（IPV4/IPV6/域名）</td>
<td>地址值，根据不同地址类型，长度不同</td>
<td>需要访问的服务器的端口号</td>
</tr>
</tbody>
</table>
<p>服务端响应：</p>
<table>
<thead>
<tr>
<th>VER</th>
<th>REP</th>
<th>RSV</th>
<th>ATYP</th>
<th>BIND.ADDR</th>
<th>BIND.PORT</th>
</tr>
</thead>
<tbody>
<tr>
<td>1byte</td>
<td>1byte</td>
<td>1byte</td>
<td>1byte</td>
<td>Variable</td>
<td>2byte</td>
</tr>
<tr>
<td>协议版本0x05为SOCKS5</td>
<td>代表响应。成功就返回0</td>
<td>保留字段（不理会）</td>
<td>地址类型（IPV4/IPV6/域名）</td>
<td>地址值（这里暂时不需要</td>
<td>端口号（这里暂时不需要</td>
</tr>
</tbody>
</table>
<blockquote>
<p>这一过程的代码：</p>
</blockquote>
<p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c31306676e3c408383a7c1a81fb2a30a~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c31306676e3c408383a7c1a81fb2a30a~tplv-k3u1fbpfcp-watermark.image?, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c31306676e3c408383a7c1a81fb2a30a~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c31306676e3c408383a7c1a81fb2a30a~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c31306676e3c408383a7c1a81fb2a30a~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<blockquote>
<p>对当前的实现进行测试：</p>
</blockquote>
<p>进行如下curl命令：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell">curl --socks5 localhost:1080 -v http://www.qq.com
</code></pre></div><p>此时请求会失败，但我们已经能看到正常打印出来的ip和端口号</p>
<h5 id="v4-实现socks5的转发阶段最终完全版本">v4-实现SOCKS5的转发阶段（最终完全版本</h5>
<p>最后的转发过程，由于不需要对流量进行任何的处理，所以没有上层协议，直接再Write操作完后把流量进行转发即可。</p>
<p>对于两个连接流量的转发，标准库里有有一些好用的函数库。</p>
<ol>
<li>
<p>通过net.Dial建立tcp连接。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="nx">dest</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="s">&#34;tcp&#34;</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;%v:%v&#34;</span><span class="p">,</span> <span class="nx">addr</span><span class="p">,</span> <span class="nx">port</span><span class="p">))</span>
<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;dial dst failed:%w&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">defer</span> <span class="nx">dest</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span>
</code></pre></div></li>
<li>
<p>标准库的 io.copy 可以实现一个单向数据转发，双向转发的话，需要启动两个 goroutinue。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">_</span><span class="p">,</span> <span class="nx">_</span> <span class="p">=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">dest</span><span class="p">,</span> <span class="nx">reader</span><span class="p">)</span>
    <span class="nf">cancel</span><span class="p">()</span>
<span class="p">}()</span>
<span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">_</span><span class="p">,</span> <span class="nx">_</span> <span class="p">=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">conn</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
    <span class="nf">cancel</span><span class="p">()</span>
<span class="p">}()</span>
</code></pre></div></li>
</ol>
<p>现在有一个问题，connect 函数会立刻返回，返回的时候连接就被关闭了。需要等待任意一个方向copy出错的时候，再返回 connect 函数。</p>
<blockquote>
<p>这个context目前还弄不明白</p>
</blockquote>
<p>这里可以使用到标准库里面的一个 context 机制，用 context 连 with cancel 来创建一个context。 在最后等待 ctx.Done() ， 只要 cancel 被调用， ctx.Done就会立刻返回。 然后在上面的两个 goroutinue 里面 调用一次 cancel 即可。</p>
<h5 id="验证">验证</h5>
<blockquote>
<p>同样是以下请求命令此时终于返回正常内容了！</p>
</blockquote>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell">curl --socks5 localhost:1080 -v http://www.qq.com
</code></pre></div><p><img
        class="lazyload"
        src="/svg/loading.min.svg"
        data-src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f22da14bdfbf45b9893a8bb6a89d9066~tplv-k3u1fbpfcp-watermark.image?"
        data-srcset="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f22da14bdfbf45b9893a8bb6a89d9066~tplv-k3u1fbpfcp-watermark.image?, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f22da14bdfbf45b9893a8bb6a89d9066~tplv-k3u1fbpfcp-watermark.image? 1.5x, https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f22da14bdfbf45b9893a8bb6a89d9066~tplv-k3u1fbpfcp-watermark.image? 2x"
        data-sizes="auto"
        alt="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f22da14bdfbf45b9893a8bb6a89d9066~tplv-k3u1fbpfcp-watermark.image?"
        title="image.png" /></p>
<p>现在SOCKS5代理服务器程序已经写好，可以使用<a href="https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif?hl=zh-CN" target="_blank" rel="noopener noreffer">SwitchyOmega</a>插件对该代理服务器进行正式的使用（可以用连接了学校内网的电脑，作为SOCKS5代理服务器对学校内网的内容进行访问(￣▽￣)&quot;</p>
</div><div class="post-footer" id="post-footer">
    <div class="post-info"><div class="post-info-tag"><span><a href="/tags/go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B/">Go语言上手</a>
                </span></div><div class="post-info-line"><div class="post-info-mod">
                <span>更新于 2022-05-07</span>
            </div><div class="post-info-mod"></div>
        </div><div class="post-info-share">
            <span><a href="javascript:void(0);" title="分享到 Twitter" data-sharer="twitter" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记" data-hashtags="Go语言上手"><i class="fab fa-twitter fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Facebook" data-sharer="facebook" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-hashtag="Go语言上手"><i class="fab fa-facebook-square fa-fw"></i></a><a href="javascript:void(0);" title="分享到 WhatsApp" data-sharer="whatsapp" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记" data-web><i class="fab fa-whatsapp fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Line" data-sharer="line" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记"><i class="fab fa-line fa-fw"></i></a><a href="javascript:void(0);" title="分享到 微博" data-sharer="weibo" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记" data-image="https://img-blog.csdnimg.cn/img_convert/acea126d07748d6630f37b1b481e5d73.png#pic_center"><i class="fab fa-weibo fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Myspace" data-sharer="myspace" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记" data-description="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。"><i data-svg-src="/lib/simple-icons/icons/myspace.min.svg"></i></a><a href="javascript:void(0);" title="分享到 Blogger" data-sharer="blogger" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记" data-description="这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记。"><i class="fab fa-blogger fa-fw"></i></a><a href="javascript:void(0);" title="分享到 Evernote" data-sharer="evernote" data-url="https://acking-you.github.io/posts/%E4%B8%80go%E8%AF%AD%E8%A8%80%E4%B8%8A%E6%89%8B-%E9%9D%92%E8%AE%AD%E8%90%A5%E7%AC%94%E8%AE%B0/" data-title="Go语言上手（一） | 青训营笔记"><i class="fab fa-evernote fa-fw"></i></a></span>
        </div></div><div class="post-nav"><a href="/posts/%E5%AE%9E%E7%8E%B0%E5%AE%9E%E6%97%B6qq%E5%A5%BD%E5%8F%8B%E6%90%9C%E7%B4%A2%E6%A1%86/" class="prev" rel="prev" title="实现实时qq好友搜索框"><i class="fas fa-angle-left fa-fw"></i>Previous Post</a>
            <a href="/posts/golang-note2/" class="next" rel="next" title="Go语言工程实践（二） | 青训营笔记">Next Post<i class="fas fa-angle-right fa-fw"></i></a></div></div>
</div></article></div>
            </main>
            <footer class="footer"><div class="footer-container"><div class="footer-line">由 <a href="https://gohugo.io/" target="_blank" rel="noopener noreffer" title="Hugo 0.86.0">Hugo</a> 强力驱动 | 主题 - <a href="https://github.com/khusika/FeelIt" target="_blank" rel="noopener noreffer" title="FeelIt 1.0.1"><i class="fas fa-hand-holding-heart fa-fw"></i> FeelIt</a>
        </div><div class="footer-line" itemscope itemtype="http://schema.org/CreativeWork"><i class="far fa-copyright fa-fw"></i><span itemprop="copyrightYear">2023</span><span class="author" itemprop="copyrightHolder">&nbsp;<a href="/"></a></span></div>
</div>
</footer>
        </div>

        <div id="fixed-buttons"><a href="#" id="back-to-top" class="fixed-button" title="回到顶部">
                <i class="fas fa-chevron-up fa-fw"></i>
            </a></div><link rel="stylesheet" href="/lib/fontawesome-free/all.min.css"><link rel="stylesheet" href="/lib/animate/animate.min.css"><link rel="stylesheet" href="/lib/katex/katex.min.css"><link rel="stylesheet" href="/lib/katex/copy-tex.min.css"><script src="/lib/autocomplete/autocomplete.min.js"></script><script src="/lib/lunr/lunr.min.js"></script><script src="/lib/lunr/lunr.stemmer.support.min.js"></script><script src="/lib/lunr/lunr.zh.min.js"></script><script src="/lib/lazysizes/lazysizes.min.js"></script><script src="/lib/clipboard/clipboard.min.js"></script><script src="/lib/sharer/sharer.min.js"></script><script src="/lib/katex/katex.min.js"></script><script src="/lib/katex/auto-render.min.js"></script><script src="/lib/katex/copy-tex.min.js"></script><script src="/lib/katex/mhchem.min.js"></script><script>window.config={"code":{"copyTitle":"复制到剪贴板","maxShownLines":200},"comment":{},"math":{"delimiters":[{"display":true,"left":"$$","right":"$$"},{"display":true,"left":"\\[","right":"\\]"},{"display":false,"left":"$","right":"$"},{"display":false,"left":"\\(","right":"\\)"}],"strict":false},"search":{"highlightTag":"em","lunrIndexURL":"/index.json","lunrLanguageCode":"zh","lunrSegmentitURL":"/lib/lunr/lunr.segmentit.js","maxResultLength":100,"noResultsFound":"没有找到结果","snippetLength":50,"type":"lunr"}};</script><script src="/js/theme.min.js"></script></body></html>
